package com.source.juccthread;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @Author wengqy
 * @Date 2021/1/20
 */
public class WaitConditionDemo {




    public static void main(String[] args) {

    Resource resource  = new Resource();
    Product product = new Product(resource);
    Consumer consumer = new Consumer(resource);

        Thread pro = new Thread(product);
        pro.setName("Product2: ");
        Thread con = new Thread(consumer);
        con.setName("Consumer2: ");


        pro.start();
        con.start();

    }


    public static  class  Resource{

        Lock lock  = new ReentrantLock();
        Condition condition1 = lock.newCondition();
        Condition condition2 = lock.newCondition();
       int  num  = 0;

       public  void  add(){

           try{
               lock.lock();
               if(num >=5){
                   try {
                       condition1.await();
                   } catch (InterruptedException e) {
                       e.printStackTrace();
                   }
               }else{
                   num  = num + 1;
                   System.out.println(Thread.currentThread().getName() + ":" + "添加了第" + num + "个产品");
                   condition2.signalAll();// 产品数量没到上线，通知其他线程来进行存或则取
               }
           }catch(Exception e){

           }finally {
lock.unlock();
           }


       }


        public   void getProduct() {
           try{
lock.lock();
               if (num <= 0) {
                   try {
                       condition2.await();
                   } catch (InterruptedException e) {
                       e.printStackTrace();
                   }
               } else {
                   System.out.println(Thread.currentThread().getName() + ":" + "买走了第" + num + "个产品");
                   num = num - 1;

                   condition1.signalAll();// 产品数量没到下线，通知其他线程来进行存或则取
               }
           }catch(Exception e){

           }finally {
               lock.unlock();
           }


        }
    }




    public   static  class  Product implements Runnable {
       private Resource resource;

        public Product(Resource resource) {
            this.resource = resource;
        }

        @Override
        public void run() {

            while(true){
                try {
                    TimeUnit.MILLISECONDS.sleep(300);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                resource.add();
            }
        }
    }



    public   static  class  Consumer implements Runnable {
        private Resource resource;

        public Consumer(Resource resource) {
            this.resource = resource;
        }

        @Override
        public void run() {

            while(true){
                try {
                    TimeUnit.MILLISECONDS.sleep(300);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                resource.getProduct();
            }
        }
    }




}
